package com.aijk.web.admin.shiro;

import com.aijk.commons.exception.ErrorCodeException;
import com.aijk.ehm.sys.api.SysAdminApi;
import com.aijk.ehm.sys.model.SysAdmin;
import com.aijk.ehm.sys.model.SysModule;
import com.aijk.web.admin.entity.Constant;
import com.aijk.web.admin.service.ModuleService;
import com.google.common.base.Objects;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.ext.CaptchaRender;
import org.apache.shiro.ext.CaptchaUsernamePasswordToken;
import org.apache.shiro.ext.IncorrectCaptchaException;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.PostConstruct;
import java.io.Serializable;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class ShiroDbRealm extends AuthorizingRealm  {

    private static final boolean hasCaptcha = false;

    @Autowired
    private SysAdminApi adminApi;
    @Autowired
    private ModuleService moduleService;


    /**
     * 认证回调函数, 登录时调用.
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        CaptchaUsernamePasswordToken authcToken = (CaptchaUsernamePasswordToken) token;
        String accountName = authcToken.getUsername();
        if (StringUtils.isBlank(accountName)) {
            throw new AuthenticationException("用户名不可以为空");
        }

        Subject subject = SecurityUtils.getSubject();
        Session session = subject.getSession(false);

        if (hasCaptcha) {
            boolean isCaptchaBlank = StringUtils.isBlank(authcToken.getCaptcha());
            if (isCaptchaBlank) {
                throw new IncorrectCaptchaException("验证码不可以为空!");
            }

            String md5Code = null;
            if (session != null) {
                md5Code = (String) session.getAttribute(CaptchaRender.DEFAULT_CAPTCHA_MD5_CODE_KEY);
            }
            boolean isRight = CaptchaRender.validate(md5Code, authcToken.getCaptcha());
            if (!isRight) {
                throw new IncorrectCaptchaException("验证码错误!");
            }

        }
        SysAdmin admin = new SysAdmin();
        admin.setUsername(accountName);
        admin.setPassword(new String(authcToken.getPassword()));
        SysAdmin adminRet = adminApi.login(admin);
        if (adminRet == null || adminRet.getSysFlag() != Constant.SYS_PE_FLAG){
            throw new ErrorCodeException("该账号不存在!");
        }
        ShiroUser shiroUser = new ShiroUser(adminRet.getUsername(), adminRet.getName(), adminRet.getAdminId(), adminRet.getAdminType(), adminRet.getSysFlag());
        //UserVo userVo= userOperateApi.login(loginInfo);
        // ShiroUser shiroUser = new ShiroUser("ceshi", "ceshi", 1,0);
        return new SimpleAuthenticationInfo(shiroUser, new String(authcToken.getPassword()).toCharArray(), getName());
        //
  /*      AdminUser user = adminUserFacade.getByLoginName(accountName);
        if (user != null) {
            if (AdminUserConst.STATUS_OFF == user.getStatus()) {
                throw new DisabledAccountException();
            }

            byte[] salt = Encodes.decodeHex(user.getSalt());
            ShiroUser shiroUser = new ShiroUser(user.getLoginName(), user.getName(), user.getId(), user.getAdminType());
            return new SimpleAuthenticationInfo(shiroUser, user.getPassword(), ByteSource.Util.bytes(salt), getName());
        } else {
            return null;
        }*/
        //  return null;
    }

    /**
     * 授权查询回调函数, 进行鉴权但缓存中无用户的授权信息时调用.
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        ShiroUser user = (ShiroUser) principals.getPrimaryPrincipal();
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

        Set<String> permissions = new HashSet<>();
        List<SysModule> list = moduleService.getUserModuleList(user);

        for (SysModule permission : list) {
            if (StringUtils.isNotEmpty(permission.getCode())) {
                permissions.add(permission.getCode());
            }
        }

        info.addStringPermissions(permissions);
        info.addRole(String.valueOf(user.getType()));
        return info;
    }

    /**
     * 设定Password校验的Hash算法与迭代次数.
     */
    @PostConstruct
    public void initCredentialsMatcher() {
     /*   HashedCredentialsMatcher matcher = new HashedCredentialsMatcher(AdminUserConst.HASH_ALGORITHM);
        matcher.setHashIterations(AdminUserConst.HASH_INTERATIONS);

        setCredentialsMatcher(matcher);*/
    }

    /**
     * 更新用户授权信息缓存.
     */
    public void clearCachedAuthorizationInfo(String principal) {
        SimplePrincipalCollection principals = new SimplePrincipalCollection(principal, getName());
        clearCachedAuthorizationInfo(principals);
    }
    /**
     * 自定义Authentication对象，使得Subject除了携带用户的登录名外还可以携带更多信息.
     */
    public static class ShiroUser implements Serializable {
        private static final long serialVersionUID = -1373760761780840081L;
        public String loginName;
        public String name;
        public int userId;
        public int type;
        public byte sysFlag;

        public ShiroUser(String loginName, String name, int userId, int type, byte sysFlag) {
            this.loginName = loginName;
            this.name = name;
            this.userId = userId;
            this.type = type;
            this.sysFlag = sysFlag;
        }

        public String getLoginName() {
            return loginName;
        }

        public int getUserId() {
            return userId;
        }

        public int getType() {
            return type;
        }

        public void setUserId(int userId) {
            this.userId = userId;
        }

        public String getName() {
            return name;
        }

        public byte getSysFlag() {
            return sysFlag;
        }


        /**
         * 本函数输出将作为默认的<shiro:principal/>输出.
         */
        @Override
        public String toString() {
            return loginName;
        }

        /**
         * 重载hashCode,只计算loginName;
         */
        @Override
        public int hashCode() {
            return Objects.hashCode(loginName);
        }

        /**
         * 重载equals,只计算loginName;
         */
        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (obj == null) {
                return false;
            }
            if (getClass() != obj.getClass()) {
                return false;
            }
            ShiroUser other = (ShiroUser) obj;
            if (loginName == null) {
                if (other.loginName != null) {
                    return false;
                }
            } else if (!loginName.equals(other.loginName)) {
                return false;
            }
            return true;
        }
    }
}
